<template>
  <div class="preview-page">
    <home-header />
    <div class="preview-content">
      <div class="toolbar">
        <el-tooltip content="导入谱子" placement="bottom">
          <el-button circle @click="onOpen"><svg class="icon" aria-hidden="true"><use :xlink:href="'#icon-folderopen'"></use></svg></el-button>
        </el-tooltip>
        <el-divider direction="vertical" class="toolbar-divider" />
        <el-tooltip content="播放" placement="bottom">
          <el-button circle @click="onPlay"><svg class="icon" aria-hidden="true"><use :xlink:href="'#icon-play'"></use></svg></el-button>
        </el-tooltip>
        <el-tooltip content="暂停" placement="bottom">
          <el-button circle @click="onStop"><svg class="icon" aria-hidden="true"><use :xlink:href="'#icon-pause'"></use></svg></el-button>
        </el-tooltip>
      </div>
      <ScoreEditor 
        ref="scoreEditor" 
        class="preview-score preview-mode" 
        :currentSymbol="currentSymbol" 
        :currentChord="currentChord"
        :enableKeyboardPlayback="true"
        :enableEdit="false"
        :showHighlight="true"
        @notePlayed="handleNotePlayed"
      />
      <div class="keyboard-box">
        <div class="piano-bottom">
          <div class="piano">
            <div v-for="(key, index) in pianoKeys" :key="index" 
                 :id="key"
                 :data-id="key"
                 class="piano-key"
                 :class="{ 'black': key.includes('#') || key.includes('b') }"
                 @click="handlePianoKeyClick(index)">
              <span v-if="noteNames[index]" :class="noteNames[index].pitch">
                {{ noteNames[index].name }}
              </span>
            </div>
          </div>
          <ul class="piano-group">
            <li v-for="(width, index) in groupWidths" 
                :key="index" 
                class="group"
                :style="{ width: width }">
              {{ index + 1 }}组
            </li>
          </ul>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import HomeHeader from '@/components/HomeHeader.vue'
import ScoreEditor from '@/components/ScoreEditor.vue'

export default {
  name: 'PreviewView',
  components: {
    HomeHeader,
    ScoreEditor
  },
  data() {
    return {
      currentSymbol: {
        duration: '四分音符',
        pitch: '小字组'
      },
      currentChord: null,
      domain: window.location.href.indexOf('localhost') !== -1 || window.location.href.indexOf('127.0.0.1') !== -1 
        ? "http://127.0.0.1:5500" 
        : "http://mainbao.gitee.io/pianosystem1",
      isCompute: false,
      intervalList: [],
      intervals: ["", "小二度", "大二度", "小三度", "大三度", "纯四度", "增四度", "纯五度", '小六度', '大六度', '小七度', '大七度', '八度', '1个八度+小二度', '1个八度+大二度'],
      functionKeys: [
        { key: "Esc", code: "27" },
        { key: "F1", code: "112" },
        { key: "F2", code: "113" },
        { key: "F3", code: "114" },
        { key: "F4", code: "115" },
        { key: "F5", code: "116" },
        { key: "F6", code: "117" },
        { key: "F7", code: "118" },
        { key: "F8", code: "119" },
        { key: "F9", code: "120" },
        { key: "F10", code: "121" },
        { key: "F11", code: "122" },
        { key: "F12", code: "123" }
      ],
      mainKeyboard: [
        { key: "`", code: "192" }, { key: "1", code: "49" }, { key: "2", code: "50" }, { key: "3", code: "51" }, { key: "4", code: "52" }, { key: "5", code: "53" }, { key: "6", code: "54" }, { key: "7", code: "55" }, { key: "8", code: "56" }, { key: "9", code: "57" }, { key: "0", code: "48" }, { key: "-", code: "189" }, { key: "+", code: "187" }, { key: "back", code: "8" },
        { key: "Tab", code: "9" }, { key: "Q", code: "81", pianoKey: '51' }, { key: "W", code: "87", pianoKey: '53' }, { key: "E", code: "69", pianoKey: '55' }, { key: "R", code: "82", pianoKey: '56' }, { key: "T", code: "84", pianoKey: '58' }, { key: "Y", code: "89", pianoKey: '60' }, { key: "U", code: "85", pianoKey: '62' }, { key: "I", code: "73" }, { key: "O", code: "79" }, { key: "P", code: "80" }, { key: "{", code: "219" }, { key: "}", code: "221" }, { key: "\\", code: "220" },
        { key: "Lock", code: "20" }, { key: "A", code: "65", pianoKey: '39' }, { key: "S", code: "83", pianoKey: '41' }, { key: "D", code: "68", pianoKey: '43' }, { key: "F", code: "70", pianoKey: '44' }, { key: "G", code: "71", pianoKey: '46' }, { key: "H", code: "72", pianoKey: '48' }, { key: "J", code: "74", pianoKey: '50' }, { key: "K", code: "75" }, { key: "L", code: "76" }, { key: ";", code: "186" }, { key: "\"", code: "222" }, { key: "Enter", code: "13", colspan2: true },
        { key: "Shift", code: "16", colspan2: true }, { key: "Z", code: "90", pianoKey: '27' }, { key: "X", code: "88", pianoKey: '29' }, { key: "C", code: "67", pianoKey: '31' }, { key: "V", code: "86", pianoKey: '32' }, { key: "B", code: "66", pianoKey: '34' }, { key: "N", code: "78", pianoKey: '36' }, { key: "M", code: "77", pianoKey: '38' }, { key: "<", code: "188" }, { key: ">", code: "190" }, { key: "?", code: "191" }, { key: "Shift", code: "16", colspan2: true },
        { key: "Ctrl", code: "17" }, { key: "win", code: "91" }, { key: "alt", code: "18" }, { key: "blank", code: "32", colspan9: true }, { key: "alt", code: "18" }, { key: "Ctrl", code: "17" }
      ],
      numpad: [
        { key: "Num", code: "144" }, { key: "/", code: "111" }, { key: "*", code: "106" }, { key: "-", code: "109" },
        { key: "7", code: "103" }, { key: "8", code: "104" }, { key: "9", code: "105" }, { key: "+", code: "107", rowspan2: true },
        { key: "4", code: "100" }, { key: "5", code: "101" }, { key: "6", code: "102" },
        { key: "1", code: "97" }, { key: "2", code: "98" }, { key: "3", code: "99" }, { key: "Enter", code: "13", rowspan2: true }, { key: "0", code: "96" },
        { key: ".", code: "110" },
      ],
      audioContext: null,
      tracks: [],
      activeDivs: [],
      audioMap: {},
      midiAccess: null,
      lastProcessedTime: 0,
      currentScale: "C 调",
      pianoKeys: [
        'A0', 'A#0/Bb0', 'B0',
        'C1', 'C#1/Db1', 'D1', 'D#1/Eb1', 'E1', 'F1', 'F#1/Gb1', 'G1', 'G#1/Ab1',
        'A1', 'A#1/Bb1', 'B1',
        'C2', 'C#2/Db2', 'D2', 'D#2/Eb2', 'E2', 'F2', 'F#2/Gb2', 'G2', 'G#2/Ab2',
        'A2', 'A#2/Bb2', 'B2',
        'C3', 'C#3/Db3', 'D3', 'D#3/Eb3', 'E3', 'F3', 'F#3/Gb3', 'G3', 'G#3/Ab3',
        'A3', 'A#3/Bb3', 'B3',
        'C4', 'C#4/Db4', 'D4', 'D#4/Eb4', 'E4', 'F4', 'F#4/Gb4', 'G4', 'G#4/Ab4',
        'A4', 'A#4/Bb4', 'B4',
        'C5', 'C#5/Db5', 'D5', 'D#5/Eb5', 'E5', 'F5', 'F#5/Gb5', 'G5', 'G#5/Ab5',
        'A5', 'A#5/Bb5', 'B5',
        'C6', 'C#6/Db6', 'D6', 'D#6/Eb6', 'E6', 'F6', 'F#6/Gb6', 'G6', 'G#6/Ab6',
        'A6', 'A#6/Bb6', 'B6',
        'C7', 'C#7/Db7', 'D7', 'D#7/Eb7', 'E7', 'F7', 'F#7/Gb7', 'G7', 'G#7/Ab7',
        'A7', 'A#7/Bb7', 'B7',
        'C8'
      ],
      scales: {
        'C 调': ['C4', 'D4', 'E4', 'F4', 'G4', 'A4', 'B4', 'C5'],
        '#C 调': ['C#4/Db4', 'D#4/Eb4', 'F4', 'F#4/Gb4', 'G#4/Ab4', 'A#4/Bb4', 'C5','C#5/Db5'],
        'D 调': ['D4', 'E4', 'F#4/Gb4', 'G4', 'A4', 'B4', 'C#5/Db5','D5'],
        '#D 调': ['D#4/Eb4', 'F4', 'G4', 'G#4/Ab4', 'A#4/Bb4', 'C5', 'D5','D#5/Eb5'],
        'E 调': ['E4', 'F#4/Gb4', 'G#4/Ab4', 'A4', 'B4', 'C#5/Db5', 'D#5/Eb5','E5'],
        'F 调': ['F4', 'G4', 'A4', 'A#4/Bb4', 'C5', 'D5', 'E5','F5'],
        '#F 调': ['F#4/Gb4', 'G#4/Ab4', 'A#4/Bb4', 'B4', 'C#5/Db5', 'D#5/Eb5','F5','F#5/Gb5'],
        'G 调': ['G4', 'A4', 'B4', 'C5', 'D5', 'E5', 'F#5/Gb5','G5'],
        '#G 调': ['G#4/Ab4', 'A#4/Bb4', 'C5', 'C#5/Db5', 'D#5/Eb5', 'F5', 'G5','G#5/Ab5'],
        'A 调': ['A4', 'B4', 'C#5/Db5', 'D5', 'E5', 'F#5/Gb5', 'G#5/Ab5','A5'],
        '#A 调': ['A#4/Bb4', 'C5', 'D5', 'D#5/Eb5', 'F5', 'G5', 'A5','A#5/Bb5'],
        'B 调': ['B4', 'C#5/Db5', 'D#5/Eb5', 'E5', 'F#5/Gb5', 'G#5/Ab5', 'A#5/Bb5','B5'],
      },
      chords: {
        'C': ['C4', 'E4', 'G4'],
        'Cm': ['C4', 'D#4/Eb4', 'G4'],
        'D': ['D4', 'F#4/Gb4', 'A4'],
        'Dm': ['D4', 'F4', 'A4'],
        'E': ['E4', 'G#4/Ab4', 'B4'],
        'Em': ['E4', 'G4', 'B4'],
        'F': ['F4', 'A4', 'C5'],
        'Fm': ['F4', 'G#4/Ab4', 'C5'],
        'G': ['G4', 'B4', 'D5'],
        'Gm': ['G4', 'A#4/Bb4', 'D5'],
        'A': ['A4', 'C#5/Db5', 'E5'],
        'Am': ['A4', 'C5', 'E5'],
      },
      songName: "修炼爱情",
      songData: [
        { chord: "F", lyrics: "的心酸", newLine: true },
        { chord: "G", lyrics: "学会放好", newLine: true },
        { chord: "Em", lyrics: "以前的渴", newLine: true },
        { chord: "Am", lyrics: "望我们", newLine: true },
        { chord: "Dm", lyrics: "那些信仰", newLine: true },
        { chord: "G", lyrics: "要忘记多", newLine: true },
        { chord: "C", lyrics: "难", newLine: true },
      ],
      noteNames: [
        { name: '6', pitch: 'QHP' },
        { name: '升6降7', pitch: 'QHP' },
        { name: '7', pitch: 'QHP' },
        { name: '1', pitch: 'THP' },
        { name: '升1降2', pitch: 'THP' },
        { name: '2', pitch: 'THP' },
        { name: '升2降3', pitch: 'THP' },
        { name: '3', pitch: 'THP' },
        { name: '4', pitch: 'THP' },
        { name: '升4降5', pitch: 'THP' },
        { name: '5', pitch: 'THP' },
        { name: '升5降6', pitch: 'THP' },
        { name: '6', pitch: 'THP' },
        { name: '升6降7', pitch: 'THP' },
        { name: '7', pitch: 'THP' },
        { name: '1', pitch: 'DHP' },
        { name: '升1降2', pitch: 'DHP' },
        { name: '2', pitch: 'DHP' },
        { name: '升2降3', pitch: 'DHP' },
        { name: '3', pitch: 'DHP' },
        { name: '4', pitch: 'DHP' },
        { name: '升4降5', pitch: 'DHP' },
        { name: '5', pitch: 'DHP' },
        { name: '升5降6', pitch: 'DHP' },
        { name: '6', pitch: 'DHP' },
        { name: '升6降7', pitch: 'DHP' },
        { name: '7', pitch: 'DHP' },
        { name: '1', pitch: 'HP' },
        { name: '升1降2', pitch: 'HP' },
        { name: '2', pitch: 'HP' },
        { name: '升2降3', pitch: 'HP' },
        { name: '3', pitch: 'HP' },
        { name: '4', pitch: 'HP' },
        { name: '升4降5', pitch: 'HP' },
        { name: '5', pitch: 'HP' },
        { name: '升5降6', pitch: 'HP' },
        { name: '6', pitch: 'HP' },
        { name: '升6降7', pitch: 'HP' },
        { name: '7', pitch: 'HP' },
        { name: '1', pitch: 'MP' },
        { name: '升1降2', pitch: 'MP' },
        { name: '2', pitch: 'MP' },
        { name: '升2降3', pitch: 'MP' },
        { name: '3', pitch: 'MP' },
        { name: '4', pitch: 'MP' },
        { name: '升4降5', pitch: 'MP' },
        { name: '5', pitch: 'MP' },
        { name: '升5降6', pitch: 'MP' },
        { name: '6', pitch: 'MP' },
        { name: '升6降7', pitch: 'MP' },
        { name: '7', pitch: 'MP' },
        { name: '1', pitch: 'LP' },
        { name: '升1降2', pitch: 'LP' },
        { name: '2', pitch: 'LP' },
        { name: '升2降3', pitch: 'LP' },
        { name: '3', pitch: 'LP' },
        { name: '4', pitch: 'LP' },
        { name: '升4降5', pitch: 'LP' },
        { name: '5', pitch: 'LP' },
        { name: '升5降6', pitch: 'LP' },
        { name: '6', pitch: 'LP' },
        { name: '升6降7', pitch: 'LP' },
        { name: '7', pitch: 'LP' },
        { name: '1', pitch: 'DLP' },
        { name: '升1降2', pitch: 'DLP' },
        { name: '2', pitch: 'DLP' },
        { name: '升2降3', pitch: 'DLP' },
        { name: '3', pitch: 'DLP' },
        { name: '4', pitch: 'DLP' },
        { name: '升4降5', pitch: 'DLP' },
        { name: '5', pitch: 'DLP' },
        { name: '升5降6', pitch: 'DLP' },
        { name: '6', pitch: 'DLP' },
        { name: '升6降7', pitch: 'DLP' },
        { name: '7', pitch: 'DLP' },
        { name: '1', pitch: 'TLP' },
        { name: '升1降2', pitch: 'TLP' },
        { name: '2', pitch: 'TLP' },
        { name: '升2降3', pitch: 'TLP' },
        { name: '3', pitch: 'TLP' },
        { name: '4', pitch: 'TLP' },
        { name: '升4降5', pitch: 'TLP' },
        { name: '5', pitch: 'TLP' },
        { name: '升5降6', pitch: 'TLP' },
        { name: '6', pitch: 'TLP' },
        { name: '升6降7', pitch: 'TLP' },
        { name: '7', pitch: 'TLP' },
        { name: '1', pitch: 'QLP' },
      ],
      keysInGroup: [3, 12, 12, 12, 12, 12, 12, 12, 1],
      groupWidths: ['3.75%', '13.35%', '13.35%', '13.35%', '13.35%', '13.35%', '13.35%', '13.35%', '1.95%'],
      showKeyboard: true,
      showName: false,
      showInterval: false,
      isPcKey: false
    }
  },
  mounted() {
    this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
    this.initializeKeyboard();
    this.highlightPianoKeysForScale(Object.keys(this.scales)[0]);
    this.generateSongLyrics();

    // Add keyboard event listeners
    document.addEventListener('keydown', this.handleKeyDown);
    document.addEventListener('keyup', this.handleKeyUp);

    // Add click event listener for chord selection
    this.$el.addEventListener('click', (e) => {
      if (e.target.classList.contains('selectKey')) {
        const selectedIndex = this.$el.querySelector('#select-tuning option:selected')?.index || 0;
        this.highlightPianoKeys(e.target.textContent, selectedIndex);
      }
    });

    // 监听谱子播放事件
    this.$nextTick(() => {
      if (this.$refs.scoreEditor?.$refs.jianpuEditor) {
        console.log('Binding notePlayed event listener');
        this.$refs.scoreEditor.$refs.jianpuEditor.$on('notePlayed', this.handleNotePlayed);
      } else {
        console.warn('ScoreEditor or JianpuEditor refs not found');
      }
    });
  },
  beforeDestroy() {
    // Remove event listeners
    document.removeEventListener('keydown', this.handleKeyDown);
    document.removeEventListener('keyup', this.handleKeyUp);
    
    // 移除谱子播放事件监听
    if (this.$refs.scoreEditor?.$refs.jianpuEditor) {
      this.$refs.scoreEditor.$refs.jianpuEditor.$off('notePlayed', this.handleNotePlayed);
    }
  },
  methods: {
    onPlay() {
      // 在播放前清除之前的高亮
      this.$el.querySelectorAll(".piano-key").forEach(key => key.classList.remove("active"));
      this.$refs.scoreEditor?.$refs.jianpuEditor?.playScore?.();
    },
    onStop() {
      // 停止播放时清除所有高亮
      this.$el.querySelectorAll(".piano-key").forEach(key => key.classList.remove("active"));
      this.$refs.scoreEditor?.$refs.jianpuEditor?.stopScore?.();
    },
    onOpen() {
      this.$refs.scoreEditor?.$refs.jianpuEditor?.openScore?.();
    },
    initializeKeyboard() {
      // Initialize keyboard layout and bindings
      this.mergedKeys = [...this.functionKeys, ...this.mainKeyboard, ...this.numpad];
    },
    highlightPianoKeys(chordName, mode) {
      this.$el.querySelectorAll(".piano-key").forEach(key => key.classList.remove("highlighted"));
      let keysToHighlight = this.chords[chordName];
      if(mode > 0) {
        let transposedChord = [];
        for (let note of keysToHighlight) {
          const index = this.pianoKeys.indexOf(note);
          if (index !== -1) {
            let transposedIndex = index + mode;
            if (transposedIndex < 0) {
              transposedIndex += this.pianoKeys.length;
            } else if (transposedIndex >= this.pianoKeys.length) {
              transposedIndex -= this.pianoKeys.length;
            }
            transposedChord.push(this.pianoKeys[transposedIndex]);
          } else {
            transposedChord.push(null);
          }
        }
        keysToHighlight = transposedChord;
      }
      keysToHighlight.forEach(key => {
        this.$el.querySelector(`.piano-key[data-id="${key}"]`)?.classList.add('highlighted');
      });
    },
    highlightPianoKeysForScale(scaleName) {
      this.$el.querySelectorAll(".piano-key").forEach(key => key.classList.remove("highlighted"));
      const keysToHighlight = this.scales[scaleName];
      keysToHighlight.forEach(key => {
        if (key.includes('#') || key.includes('b')) {
          const index = this.pianoKeys.indexOf(key);
          this.$el.querySelector(`.piano-key:nth-child(${index + 1})`)?.classList.add('highlighted');
        } else {
          this.$el.querySelector(`#${key}`)?.classList.add('highlighted');
        }
      });
    },
    handlePianoKeyClick(index) {
      if (!this.isCompute) {
        const id = this.pianoKeys[index];
        const audio = new Audio();
        let noteName;
        if (id.includes('/')) {
          noteName = id.split('/')[1];
        } else {
          noteName = id;
        }
        audio.src = `/audio/salamander/${noteName}.mp3`;
        audio.onerror = (e) => {
          console.error('Error loading audio:', e);
          this.$message.error('音频加载失败');
        };
        audio.currentTime = 0;
        audio.play().catch(error => {
          console.error('Error playing audio:', error);
          this.$message.error('音频播放失败');
        });
      } else {
        if (this.intervalList.length < 8) {
          const name = this.pianoKeys[index];
          if (this.intervalList.includes(name)) {
            this.intervalList = this.intervalList.filter(item => item !== name);
            this.$el.querySelector(`.piano-key:nth-child(${index + 1})`)?.classList.remove('highlighted');
          } else {
            this.intervalList.push(name);
            this.$el.querySelector(`.piano-key:nth-child(${index + 1})`)?.classList.add('highlighted');
          }
          this.updateIntervalList(this.intervalList);
        } else {
          this.$message.error('长度不要超过8个音符');
        }
      }
    },
    handleShowNameChange() {
      const spans = this.$el.querySelectorAll('.piano-key span');
      spans.forEach(span => {
        span.style.display = this.showName ? 'block' : 'none';
      });
    },
    handleShowKeyboardChange() {
      console.log('Keyboard visibility changed:', this.showKeyboard);
    },
    handleShowIntervalChange() {
      const intervalElements = this.$el.querySelectorAll('.interval');
      intervalElements.forEach(el => {
        el.style.display = this.showInterval ? 'block' : 'none';
      });
    },
    handleIsPcKeyChange() {
      // Visibility is handled by v-show
    },
    handleMIDISwitch() {
      if (this.showKeyboard) {
        if (navigator.requestMIDIAccess) {
          navigator.requestMIDIAccess()
            .then(this.onMIDISuccess)
            .catch(error => {
              console.error("无法访问MIDI设备:", error);
              this.$message.error('浏览器不支持MIDI!');
              this.showKeyboard = false;
            });
        } else {
          this.$message.error('浏览器不支持MIDI!');
          this.showKeyboard = false;
        }
      } else {
        this.$message.error('断开连接');
        this.disconnectMIDI();
        this.$el.querySelector('.mini-name').innerHTML = '';
      }
    },
    updateIntervalList(keys) {
      const intervalList = this.$el.querySelector('.interval-list');
      intervalList.innerHTML = '';
      
      keys.sort((a, b) => this.pianoKeys.indexOf(a) - this.pianoKeys.indexOf(b));
      
      keys.forEach((key, index) => {
        let nameArr;
        if (key.includes('#') || key.includes('b')) {
          nameArr = key.split("/")[0].split("");
          intervalList.innerHTML += `<div class='interval-sound' data-key='${key}'>${nameArr[1]}${nameArr[0]}<small>${nameArr[2]}</small></div>`;
        } else {
          nameArr = key.split("");
          intervalList.innerHTML += `<div class='interval-sound' data-key='${key}'>${nameArr[0]}<small>${nameArr[1]}</small></div>`;
        }
        
        if (index > 0) {
          const result = this.pianoKeys.indexOf(keys[index]) - this.pianoKeys.indexOf(keys[index - 1]);
          if (typeof this.intervals[result] === 'undefined') {
            this.$message.error('不要乱点跨度太大了!');
            this.$el.querySelector('.interval-sound:last-child')?.remove();
          } else {
            const intervalName = document.createElement('div');
            intervalName.className = 'interval-name';
            intervalName.textContent = this.intervals[result];
            this.$el.querySelector('.interval-sound:last-child')?.before(intervalName);
          }
        }
      });
    },
    generateSongLyrics() {
      const lyricsContainer = this.$el.querySelector('.lyrics-content');
      if (!lyricsContainer) return;
      
      lyricsContainer.innerHTML = '';
      this.songData.forEach(line => {
        if (line.newLine) {
          lyricsContainer.innerHTML += `
            <div class="line song-line">
              <p><span class="chord selectKey">${line.chord}</span></p>
              <p>${line.lyrics}</p>
            </div>`;
        } else {
          lyricsContainer.innerHTML += `
            <br/>
            <div class="line song-line">
              <p><span class="chord selectKey">${line.chord}</span> ${line.lyrics}</p>
            </div>`;
        }
      });
    },
    playTrack(index, key) {
      if (index === null || index === undefined || index < 0 || index >= this.pianoKeys.length) {
        console.warn('Invalid piano key index:', index);
        return;
      }

      if (!this.audioMap[index]) {
        const audio = new Audio();
        const id = this.pianoKeys[index];
        let noteName;
        if (id.includes('/')) {
          noteName = id.split('/')[1];
        } else {
          noteName = id;
        }
        audio.src = `/audio/salamander/${noteName}.mp3`;
        audio.onerror = (e) => {
          console.error('Error loading audio:', e);
          this.$message.error('音频加载失败');
          return;
        };
        
        const track = this.audioContext.createMediaElementSource(audio);
        const merger = this.audioContext.createChannelMerger(2);
        track.connect(merger);
        merger.connect(this.audioContext.destination);
        
        audio.play().catch(error => {
          console.error('Error playing audio:', error);
          this.$message.error('音频播放失败');
          return;
        });
        
        this.audioMap[index] = { audio, playing: true };
        this.highlightDiv(index, key);
      }
    },
    highlightDiv(index, key) {
      this.$el.querySelector(`.piano-key:nth-child(${index + 1})`)?.classList.add('active');
      this.$el.querySelector(`.key[data-code="${key}"]`)?.classList.add('active');
      this.$el.querySelector(`.pc-key-item:nth-child(${index + 1})`)?.classList.add('tantiao');
      this.activeDivs.push(index);
    },
    unhighlightDiv(index, key) {
      this.$el.querySelector(`.piano-key:nth-child(${index + 1})`)?.classList.remove('active');
      this.$el.querySelector(`.key[data-code="${key}"]`)?.classList.remove('active');
      this.$el.querySelector(`.pc-key-item:nth-child(${index + 1})`)?.classList.remove('tantiao');
      this.activeDivs = this.activeDivs.filter(item => item !== index);
    },
    stopAllTracks() {
      Object.values(this.audioMap).forEach(item => {
        const { audio, playing } = item;
        if (playing) {
          audio.addEventListener('ended', () => {
            audio.pause();
            audio.currentTime = 0;
          }, { once: true });
        } else {
          audio.pause();
          audio.currentTime = 0;
        }
      });
      this.audioMap = {};
      this.activeDivs.forEach(index => this.unhighlightDiv(index));
      this.activeDivs = [];
    },
    createTrack(src) {
      const audio = new Audio(`${this.domain}/mp3/${src}`);
      const track = this.audioContext.createMediaElementSource(audio);
      return { audio, track };
    },
    findPianoKeyByCode(num) {
      const mergedKeys = [...this.functionKeys, ...this.mainKeyboard, ...this.numpad];
      const key = mergedKeys.find(k => k.code === num.toString());
      return key?.pianoKey || null;
    },
    findPianoKeyByKey(index) {
      if (index) {
        const mergedKeys = [...this.functionKeys, ...this.mainKeyboard, ...this.numpad];
        const key = mergedKeys.find(k => k.pianoKey === index.toString());
        return key?.code || null;
      }
      return null;
    },
    handleKeyDown(e) {
      const activeElement = document.activeElement;
      if (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA') {
        return;
      }
      const key = e.which;
      const keyIndex = this.findPianoKeyByCode(key);
      if (keyIndex !== null && keyIndex !== undefined) {
        this.playTrack(keyIndex, key);
      }
    },
    handleKeyUp() {
      this.stopAllTracks();
    },
    onMIDISuccess(midiAccess) {
      console.log('MIDI ready!');
      this.midiAccess = midiAccess;
      const inputs = midiAccess.inputs;

      if (midiAccess.inputs.size > 0) {
        this.$message.success('连接成功!');
        inputs.forEach(input => {
          this.$el.querySelector('.mini-name').innerHTML = `<span class="state"></span>设备名称：${input.name}`;
          input.onmidimessage = this.getMIDIMessage;
        });
      } else {
        this.$message.error('未找到MIDI设备!');
        this.showKeyboard = false;
      }

      midiAccess.onstatechange = (event) => {
        const inputs = midiAccess.inputs.values();
        const inputsArray = Array.from(inputs);

        if (inputsArray.length === 0) {
          this.$message.error('MIDI设备已关闭!');
          this.$el.querySelector('.mini-name').innerHTML = '';
          this.showKeyboard = false;
        }
      };
    },
    onMIDIFailure(error) {
      this.$message.error('连接失败!');
      this.showKeyboard = false;
    },
    getMIDIMessage(event) {
      const currentTime = Date.now();
      const timeDiff = currentTime - this.lastProcessedTime;

      const command = event.data[0];
      const index = event.data[1];
      const velocity = event.data.length > 2 ? event.data[2] : 0;
      const key = this.findPianoKeyByKey(index - 21);

      switch (command) {
        case 144: // Note On
          if (velocity !== 0) {
            this.highlightDiv(index - 21, key);
          }
          break;
        case 248: // Note Off
          if (timeDiff >= 1000) {
            this.activeDivs.forEach(index => this.unhighlightDiv(index));
            this.lastProcessedTime = currentTime;
          }
          break;
      }
    },
    disconnectMIDI() {
      if (this.midiAccess) {
        this.midiAccess.inputs.forEach(input => {
          input.onmidimessage = null;
        });
        console.log("MIDI disconnected.");
      } else {
        console.warn("MIDI not connected.");
      }
    },
    handleShowNameChange() {
      const spans = this.$el.querySelectorAll('.piano-key span');
      spans.forEach(span => {
        span.style.display = this.showName ? 'block' : 'none';
      });
    },
    handleShowIntervalChange() {
      const intervalElements = this.$el.querySelectorAll('.interval');
      intervalElements.forEach(el => {
        el.style.display = this.showInterval ? 'block' : 'none';
      });
    },
    handleIsPcKeyChange() {
      // Visibility is handled by v-show
    },
    handleMIDISwitch() {
      if (this.showKeyboard) {
        if (navigator.requestMIDIAccess) {
          navigator.requestMIDIAccess()
            .then(this.onMIDISuccess)
            .catch(error => {
              console.error("无法访问MIDI设备:", error);
              this.$message.error('浏览器不支持MIDI!');
              this.showKeyboard = false;
            });
        } else {
          this.$message.error('浏览器不支持MIDI!');
          this.showKeyboard = false;
        }
      } else {
        this.$message.error('断开连接');
        this.disconnectMIDI();
        this.$el.querySelector('.mini-name').innerHTML = '';
      }
    },
    updateIntervalList(keys) {
      const intervalList = this.$el.querySelector('.interval-list');
      intervalList.innerHTML = '';
      
      keys.sort((a, b) => this.pianoKeys.indexOf(a) - this.pianoKeys.indexOf(b));
      
      keys.forEach((key, index) => {
        let nameArr;
        if (key.includes('#') || key.includes('b')) {
          nameArr = key.split("/")[0].split("");
          intervalList.innerHTML += `<div class='interval-sound' data-key='${key}'>${nameArr[1]}${nameArr[0]}<small>${nameArr[2]}</small></div>`;
        } else {
          nameArr = key.split("");
          intervalList.innerHTML += `<div class='interval-sound' data-key='${key}'>${nameArr[0]}<small>${nameArr[1]}</small></div>`;
        }
        
        if (index > 0) {
          const result = this.pianoKeys.indexOf(keys[index]) - this.pianoKeys.indexOf(keys[index - 1]);
          if (typeof this.intervals[result] === 'undefined') {
            this.$message.error('不要乱点跨度太大了!');
            this.$el.querySelector('.interval-sound:last-child')?.remove();
          } else {
            const intervalName = document.createElement('div');
            intervalName.className = 'interval-name';
            intervalName.textContent = this.intervals[result];
            this.$el.querySelector('.interval-sound:last-child')?.before(intervalName);
          }
        }
      });
    },
    generateSongLyrics() {
      const lyricsContainer = this.$el.querySelector('.lyrics-content');
      if (!lyricsContainer) return;
      
      lyricsContainer.innerHTML = '';
      this.songData.forEach(line => {
        if (line.newLine) {
          lyricsContainer.innerHTML += `
            <div class="line song-line">
              <p><span class="chord selectKey">${line.chord}</span></p>
              <p>${line.lyrics}</p>
            </div>`;
        } else {
          lyricsContainer.innerHTML += `
            <br/>
            <div class="line song-line">
              <p><span class="chord selectKey">${line.chord}</span> ${line.lyrics}</p>
            </div>`;
        }
      });
    },
    handleNotePlayed(note, cell) {
      console.log('Note played:', note, cell);
      // 将简谱音符转换为钢琴键索引
      const noteIndex = this.getPianoKeyIndex(note, cell);
      console.log('Piano key index:', noteIndex);
      if (noteIndex !== -1) {
        // 高亮对应的钢琴键
        const pianoKey = this.$el.querySelector(`.piano-key:nth-child(${noteIndex + 1})`);
        if (pianoKey) {
          pianoKey.classList.add('active');
          // 300ms 后移除高亮
          setTimeout(() => {
            pianoKey.classList.remove('active');
          }, 300);
        } else {
          console.warn('Piano key element not found for index:', noteIndex);
        }
      } else {
        console.warn('Invalid piano key index calculated for note:', note);
      }
    },
    getPianoKeyIndex(note, cell) {
      // 根据当前调式确定基准音符
      const scale = this.scales[this.currentScale];
      if (!scale) return -1;

      // 获取基准音符的索引（使用C4作为基准）
      const baseNoteIndex = this.pianoKeys.indexOf('C4');
      if (baseNoteIndex === -1) return -1;

      // 计算目标音符的索引
      // 简谱音符范围是 1-7，需要转换为 0-6
      const noteValue = (note - 1) % 7;
      
      // 获取当前调式的音阶
      const scaleNotes = scale.slice(0, 7); // 只取一个八度的音阶
      
      // 根据音阶中的音符位置计算实际索引
      const targetNote = scaleNotes[noteValue];
      if (!targetNote) return -1;
      
      // 找到目标音符在钢琴键数组中的索引
      const targetIndex = this.pianoKeys.indexOf(targetNote);
      if (targetIndex === -1) return -1;

      // 计算八度偏移
      let octaveOffset = 0;
      if (cell) {
        // 根据音高组计算八度偏移
        if (cell.pitch === '大字二组') {
          octaveOffset = -48; // 降低四个八度
        } else if (cell.pitch === '大字一组') {
          octaveOffset = -36; // 降低三个八度
        } else if (cell.pitch === '大字组') {
          octaveOffset = -24; // 降低两个八度
        } else if (cell.pitch === '小字组') {
          octaveOffset = -12; // 降低一个八度
        } else if (cell.pitch === '小字一组') {
          octaveOffset = 0; // 基准八度
        } else if (cell.pitch === '小字二组') {
          octaveOffset = 12; // 升高一个八度
        } else if (cell.pitch === '小字三组') {
          octaveOffset = 24; // 升高两个八度
        } else if (cell.pitch === '小字四组') {
          octaveOffset = 36; // 升高三个八度
        } else if (cell.pitch === '小字五组') {
          octaveOffset = 48; // 升高四个八度
        }
      }
      
      // 计算最终索引
      const finalIndex = targetIndex + octaveOffset;
      
      // 确保索引在有效范围内
      if (finalIndex < 0 || finalIndex >= this.pianoKeys.length) {
        console.warn('Invalid piano key index:', finalIndex, 'for note:', note, 'pitch:', cell?.pitch);
        return -1;
      }
      
      return finalIndex;
    }
  }
}
</script>

<style scoped>
.preview-page {
  min-height: 100vh;
  background-color: #f5f7fa;
}

.preview-content {
  padding: 80px 10px 0px;
  margin: 0 auto;
}

.toolbar {
  width: 100%;
  background: var(--surface-color);
  box-shadow: var(--shadow-sm);
  padding: 12px 24px;
  display: flex;
  align-items: center;
  gap: 8px;
  border-bottom: 1px solid var(--border-color);
  margin-bottom: 0;
  border-radius: 12px 12px 0 0;
}

.toolbar-divider {
  margin: 0 8px;
  height: 24px;
  background-color: var(--border-color);
}

.icon {
  width: 18px;
  height: 18px;
  vertical-align: middle;
  fill: currentColor;
  transition: transform 0.2s ease;
}

.el-button {
  width: 36px;
  height: 36px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  transition: all 0.2s ease;
  color: var(--text-secondary);
  background: transparent;
  border: 1px solid transparent;
}

.el-button:hover {
  color: var(--primary-color);
  background: rgba(37, 99, 235, 0.1);
  border-color: transparent;
  transform: translateY(-1px);
}

.el-button:active {
  transform: translateY(0);
}

.el-button .icon {
  font-size: 18px;
}

:deep(.el-tooltip__popper) {
  font-size: 12px;
  padding: 6px 12px;
  border-radius: 6px;
  background: var(--text-primary);
  color: white;
  box-shadow: var(--shadow-md);
}

.preview-score {
  background: var(--surface-color);
  border-radius: 0 0 12px 12px;
  box-shadow: var(--shadow-md);
  border: 1px solid var(--border-color);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  height: calc(100vh - 316px);
}

h1 {
  color: #222;
  margin-bottom: 24px;
}

.keyboard-name {
  margin-top: 20px;
  padding: 16px 24px;
  background: var(--surface-color);
  border-radius: 12px;
  box-shadow: var(--shadow-md);
  border: 1px solid var(--border-color);
  font-size: 16px;
  color: var(--text-primary);
}

.keyboard-name .name {
  font-weight: 500;
  color: var(--primary-color);
  margin-left: 8px;
}

@media (max-width: 768px) {
  .preview-content {
    padding: 80px 20px 20px;
  }
}

/* Piano and Keyboard Styles */
.piano-main {
  height: calc(100vh - 200px);
  background: #1d1d1d;
  background-image: linear-gradient(to top, #adcefc, #96c4fd);
}

.piano-bottom {
  height: 175px;
  background: #000;
  width: 100%;
}

.piano-left {
  width: 80%;
  float: left;
  height: calc(100vh - 200px);
}

.piano-right {
  width: 20%;
  float: left;
  background: #fff;
  height: calc(100vh - 200px);
  overflow-y: auto;
  position: relative;
}

.piano-box {
  overflow: hidden;
}

.piano {
  display: flex;
  justify-content: space-between;
  background: #fff;
  width: 100%;
  border: 1px solid #000;
  border-top-width: 3px;
  box-sizing: border-box;
  height: 156px;
}

.piano-key {
  width: 2%;
  height: 152px;
  outline: 1px solid #444444;
  background-color: white;
  box-sizing: border-box;
  line-height: 240px;
  text-align: center;
  position: relative;
  border-radius: 0 0 2px 2px;
  border-bottom: 5px solid #eeeeee;
  cursor: pointer;
  -webkit-user-select: none;
}

.piano-key.black {
  border: none;
  color: #ccc;
  font-size: 12px !important;
  height: 90px;
  display: flex;
  align-items: flex-end;
  padding-bottom: 5px;
  width: 0.9%;
  height: 100px;
  margin: 0 -10px;
  background-color: #444444;
  z-index: 2;
  line-height: normal;
  color: #fff;
  writing-mode: inherit;
}

.piano-key:active {
  background: #000;
  color: #fff !important;
  border-bottom: 5px solid #000;
}

.piano-key.black:active {
  border-bottom: none;
}

.piano-key.active,
.piano-key.active span:after {
  background: red;
  color: #fff !important;
  border-bottom: 5px solid red;
}

.piano-key:active span::after {
  color: #fff !important;
}

.piano-key span::after {
  position: absolute;
  bottom: 36px;
  left: 50%;
  margin-left: -5px;
  display: inline-block;
  width: 10px;
  font-size: 12px;
  line-height: 0;
  text-align: center;
  color: #000;
  writing-mode: tb;
  box-sizing: border-box;
}

.piano-key .LP::after {
  height: 4px;
  content: '.';
}

.piano-key .DLP::after {
  height: 6px;
  content: '..';
}

.piano-key .TLP::after {
  height: 8px;
  content: '...';
}

.piano-key .QLP::after {
  height: 10px;
  content: '....';
}

.piano-key .HP::after {
  height: 4px;
  bottom: 13px;
  content: '.';
}

.piano-key .DHP::after {
  bottom: 10px;
  height: 6px;
  content: '..';
}

.piano-key .THP::after {
  bottom: 8px;
  height: 8px;
  content: '...';
}

.piano-key .QHP::after {
  bottom: 8px;
  height: 8px;
  content: '....';
}

.piano-group {
  overflow: hidden;
  border: 1px solid #000;
  border-width: 0 0.1% 0 0.1%;
}

.piano-group li {
  float: left;
  width: auto;
  background: #ccc;
  font-size: 12px;
  color: #333;
}

.group {
  list-style: none;
  text-align: center;
  margin-top: 3px;
  margin-right: 0.1%;
  box-sizing: border-box;
  white-space: nowrap;
}

.group:last-child {
  margin-right: 0;
}

/* Keyboard Map Styles */
.keyboard-box {
  position: relative;
  width: 100%;
  overflow: hidden;
}

.piano-bottom {
  height: 175px;
  background: #000;
  width: 100%;
}

.piano {
  display: flex;
  justify-content: space-between;
  background: #fff;
  width: 100%;
  border: 1px solid #000;
  border-top-width: 3px;
  box-sizing: border-box;
  height: 156px;
}

/* Main Keyboard Styles */
.main-keyboard {
  grid-area: main-keyboard;
  display: grid;
  grid-template-columns: repeat(14, 1fr);
  grid-template-rows: repeat(4, 1fr);
  gap: 5px;
  border-radius: 5px;
  padding: 5px;
}

.numpad {
  grid-area: numpad;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(4, 1fr);
  gap: 5px;
  border-radius: 5px;
  padding: 5px;
}

#keyboard {
  display: grid;
  grid-template-areas:
    "function-keys function-keys"
    "main-keyboard numpad";
  gap: 9px;
  border-radius: 5px;
  background-image: linear-gradient(to top, #f9f9f9, #fff);
  padding: 10px;
  box-sizing: border-box;
  margin: 10px;
  font-size: 12px;
  color: #666;
  user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  -webkit-user-select: none;
  margin-top: 30px;
  box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.4);
}

.function-keys {
  grid-area: function-keys;
  display: flex;
  gap: 15px;
  border-radius: 5px;
  padding: 5px;
}

.key {
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 5px;
  border: 1px solid #ccc;
  background-color: #f0f0f0;
  cursor: pointer;
  transition: background-color 0.3s ease;
  padding: 9px;
  font-size: 14px;
  min-width: 30px;
  box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
}

.key:hover {
  background-color: #999;
  color: #fff;
}

.key.active {
  background: red;
  color: #fff;
  box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
  transform: translate(1px, 1px);
}

.key.colspan2 {
  grid-column: span 2;
  min-width: 60px;
}

.key.colspan9 {
  grid-column: span 9;
  min-width: 60px;
}

.key.rowspan2 {
  grid-row: span 2;
}

/* Switch Styles */
.switch-box {
  position: relative;
  display: inline-block;
  width: 60px;
  height: 28px;
  margin-top: 6px;
  overflow: hidden;
}

.switch-input {
  display: none;
}

.switch-label {
  display: block;
  width: 100%;
  height: 100%;
  cursor: pointer;
  background: #ccc;
  border-radius: 17px;
  position: relative;
}

.switch-box .txt {
  display: inline-block;
}

.switch-label:before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 26px;
  height: 26px;
  background: white;
  border-radius: 50%;
  transition: 0.3s;
}

.switch-input:checked+.switch-label {
  background: #007bff;
}

.switch-input:checked+.switch-label:before {
  transform: translateX(34px);
}

.mini-name {
  padding: 20px 0 0 10px;
  color: #333;
}

.state {
  display: inline-block;
  width: 15px;
  height: 15px;
  margin-right: 5px;
  vertical-align: middle;
  background-color: #23d96e;
  border-radius: 100%;
  outline: 1px solid #f9f9f9;
}

/* Chord Type Styles */
.chord-type {
  margin-top: 20px;
  padding: 0 15px;
}

.chord-type-title {
  width: 30px;
  text-align: center;
  font-size: 16px !important;
  background: #efa41b;
  color: #fff;
  font-weight: bold !important;
}

.chord-type-table {
  margin-top: 10px;
  background: #fff;
  width: 100%;
  border-collapse: collapse;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid #f86e6e;
  outline: 2px solid #666;
  box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.4);
}

.chord-type-table td {
  border: 1px solid #eee;
  padding: 10px;
  font-size: 14px;
}

.chordp-type-item {
  display: inline-block;
  padding: 5px 10px;
  background: #f5f5f5;
  color: #666;
  margin-right: 5px;
  margin-bottom: 5px;
}

.preview-mode {
  pointer-events: none;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}

.preview-mode :deep(.cell) {
  cursor: default;
}

.preview-mode :deep(.measure-group) {
  cursor: default;
}

.preview-mode :deep(.selected-measure) {
  filter: none;
}
</style> 